
//Refactor
//////
#define WIN32
//////

#ifdef WIN32

#ifndef WIN32THREADHELPER_H
#define WIN32THREADHELPER_H

#include <windows.h>
#include <process.h>
#include <assert.h>
#include <stdlib.h> 
#include <stdio.h>

typedef unsigned THREAD_RESULT;
#define __THREAD__ __stdcall
#define threadfunc THREAD_RESULT  __THREAD__
#define currentThreadID GetCurrentThreadId()
#define currentProcessID()  ((int)GetCurrentProcessId())
typedef THREAD_RESULT ( __THREAD__ *ThreadFunc)(void*);
#define thread_selfID() ((int)(currentThreadID))	
#define thread_pid() currentProcessID()

static int currentSeqNo;  


typedef HANDLE hthread;
static __declspec(thread) int currentThreadSeqNo;

typedef struct
{
   ThreadFunc threadFunc; 
   void* parm;           
} ThreadParm;

static struct mutex_t
{
   HANDLE handle;
};

 static mutex_t* printfMutex;

static void mutex_lock(const mutex_t* mutex)
{
   DWORD result = WaitForSingleObject(mutex->handle, INFINITE);
   assert(result == WAIT_OBJECT_0);
}

static void mutex_unlock(const mutex_t* mutex)
{
   ReleaseMutex(mutex->handle);
}

static mutex_t* mutex_create()
{
   mutex_t* mutex = (mutex_t*)calloc(1, sizeof(mutex_t));
   assert(mutex);

   mutex->handle = CreateMutex(
      NULL, 
      FALSE, 
      NULL   
      );

   assert(mutex->handle);

   return mutex;
}

 static void thread_init()
{
    printfMutex = mutex_create();
}


 static void thread_printf(const char* format, ...)
{
   va_list parms;
   va_start(parms,format);
   assert(format);
   vprintf(format, parms);
   fflush(stdout);
}


static int thread_selfSeqNo()
{
   return currentThreadSeqNo;
}

static void createThread(ThreadFunc threadFunc, void* arg)
{

   HANDLE hThread = (HANDLE)_beginthreadex(
      NULL,       
      0,          
      threadFunc, 
      arg,        
      0,
      NULL
      );
} 

static threadfunc proxyThreadFunc(void* _parm)
{
   ThreadParm* threadParm = (ThreadParm*)_parm;
   ThreadFunc threadFunc = threadParm->threadFunc;
   void* parm = threadParm->parm;
   free(threadParm);
   currentThreadSeqNo = ++currentSeqNo;
   return threadFunc(parm);
}

static void thread_addThreads(int n, ThreadFunc threadFunc, void* parm)
{
   int i;

   for (i = 0; i < n; i++)
   {
      ThreadParm* threadParm = (ThreadParm*)calloc(1, sizeof(ThreadParm));
      threadParm->threadFunc = threadFunc;
      threadParm->parm = parm;
      createThread(proxyThreadFunc, threadParm);
   }
}
#endif

#endif //WIn32